#ifndef ___fat32_transaccionA4_eliminar_directorio

#define ___fat32_transaccionA4_eliminar_directorio 1

#include "f32_mto.c"

#include "f32_st01.c"
#include "f32_st02.c"
#include "f32_st06.c"
#include "f32_st10.c"
#include "f32_st11.c"
#include "f32_st12.c"
#include "f32_st13.c"
#include "f32_st17.c"

enum fat32trA4_errores {
  FAT32_A4_NO_EXISTE_DIRECTORIO = 1,
  FAT32_A4_ES_ARCHIVO = 2,
  FAT32_A4_INTENTO_ELIMINAR_LA_RAIZ = 3
};

struct fat32trA4_datos_entrada {
  unsigned int remitente;
  char * directorio;
};

struct fat32trA4_datos_internos {
  unsigned int remitenteMensaje;
  char * directorioElim;
  char ** rutaElim;
  unsigned long long descriptor;
  unsigned int conexion;
  void * datosInternos;
  struct fat32_ref_entrada_directorio entrada;
  fat32_lista_bloques_para_escribir * lbpe1;
  signed short errorDevuelto;
  struct fat32_atributos_archivo atributos;
};

void fat32tr_eliminar_directorio(char *, unsigned int);
int fat32ctr_eliminar_directorio(FAT32_PARAMS_CREACION_TRANSACCION);
int fat32etr_eliminar_directorio(FAT32_PARAMS_TRANSACCION);

void fat32tr_eliminar_directorio (char * directorio, unsigned int remitente) {
  struct fat32trA4_datos_entrada datos;
  datos.remitente = remitente;
  datos.directorio = malloc(1 + strlen(directorio));
  memcpy(datos.directorio, directorio, 1 + strlen(directorio));
  fat32_crear_transaccion(&fat32ctr_eliminar_directorio, &datos, sizeof datos);
}

int fat32ctr_eliminar_directorio (FAT32_PARAMS_CREACION_TRANSACCION) {
  struct fat32trA4_datos_entrada * de = datosIniciales;
  struct fat32trA4_datos_internos * di = malloc(sizeof(struct fat32trA4_datos_internos));
  di -> remitenteMensaje = de -> remitente;
  di -> directorioElim = de -> directorio;
  *datos = di;
  *handler = &fat32etr_eliminar_directorio;
  return 0xE100;
}

int fat32etr_eliminar_directorio (FAT32_PARAMS_TRANSACCION) {
  unsigned char estado1;
  int estado2;
  estado2 = estado >> 8;
  estado1 = estado & 255;
  struct fat32trA4_datos_internos * datosT = *datos;
  switch (estado2) {
  case 0x01:
    estado1 = fat32st_obtener_conexion(estado1, numeroTransaccion, &(datosT -> conexion), resultadoOperacion, datosOperacion);
    if (!estado1) estado2 = 0x02;
    break;
  case 0x02:
    estado1 = fat32st_ubicar_entrada_directorio(estado1, numeroTransaccion, datosT -> rutaElim, &(datosT -> datosInternos),
                                                                                        resultadoOperacion, datosOperacion);
    if (!estado1) {
      datosT -> entrada = *((struct fat32_ref_entrada_directorio *) datosT -> datosInternos);
      free(datosT -> datosInternos);
      estado2 = 0xE1;
      estado1 = 1;
    }
    break;
  case 0x03:
    estado1 = fat32st_obtener_atributos(estado1, numeroTransaccion, (datosT -> entrada).clusterInicial, (datosT -> entrada).posicionEntrada,
                                                                             &(datosT -> datosInternos), resultadoOperacion, datosOperacion);
    if (!estado1) {
      datosT -> atributos = *((struct fat32_atributos_archivo *) (datosT -> datosInternos));
      free(datosT -> datosInternos);
      estado2 = 0xE1;
      estado1 = 2;
    }
    break;
  case 0x04:
    estado1 = fat32st_bloquear_directorio_total(estado1, numeroTransaccion, datosT -> descriptor, resultadoOperacion);
    if (!estado1) estado2 = 0x05;
    break;
  case 0x05:
    estado1 = fat32st_eliminar_directorio_completo(estado1, numeroTransaccion, (datosT -> entrada).clusterInicial,
                                                   (datosT -> entrada).posicionEntrada, &(datosT -> datosInternos), resultadoOperacion,
                                                   datosOperacion);
    if (!estado1) {
      datosT -> lbpe1 = datosT -> datosInternos;
      estado2 = 0x06;
    }
  case 0x06:
    estado1 = fat32st_ejecutar_lista_bloques_para_escribir(estado1, numeroTransaccion, datosT -> lbpe, &(datosT -> datosInternos),
                                                                                               resultadoOperacion, datosOperacion);
    if (!estado1) estado2 = 0x07;
    break;
  case 0x07:
    estado1 = fat32st_liberar_bloqueo(estado1, numeroTransaccion, datosT -> descriptor);
    if (!estado1) {
      estado2 = 0xE1;
      estado1 = 3;
    }
    break;
  case 0x08:
    estado1 = fat32st_liberar_conexion(estado1, numeroTransaccion);
    if (!estado1) {
      estado2 = 0xE1;
      estado1 = 4;
    }
    break;
  case 0xE1:
    switch (estado1) {
    case 0:
      if (strlen(datosT -> directorioElim) < 2) {
        mtf_enviar_mensaje(fat32_centro_mensajes, datosT -> remitenteMensaje, MTR_DIRECTORIO_NO_BORRO, datosT -> directorioElim,
                                                                                        (int) FAT32_A4_INTENTO_ELIMINAR_LA_RAIZ);
        free(datosT -> directorioElim);
        free(datosT);
        estado1 = 0;
        estado2 = 0;
      } else {
        datosT -> rutaElim = fat32_obtener_ruta(datosT -> directorioElim);
        datosT -> descriptor = fat32_generar_descriptor(datosT -> rutaElim, 1);
        datosT -> errorDevuelto = -1;
        estado2 = 0x01;
      }
      break;
    case 1:
      if ((datosT -> entrada).resultado) {
        datosT -> errorDevuelto = FAT32_A4_NO_EXISTE_DIRECTORIO;
        estado1 = 3;
      } else {
        estado1 = 0;
        estado2 = 0x03;
      }
      break;
    case 2:
      if ((datosT -> atributos).hardlinks == -1) {
        datosT -> errorDevuelto = FAT32_A4_ES_ARCHIVO;
        estado1 = 3;
      } else {
        estado1 = 0;
        estado2 = 0x04;
      }
      break;
    case 3:
      if ((datosT -> errorDevuelto) == -1)
        mtf_enviar_mensaje(fat32_centro_mensajes, datosT -> remitenteMensaje, MTR_DIRECTORIO_ELIMINO, datosT -> directorioElim);
      else
        mtf_enviar_mensaje(fat32_centro_mensajes, datosT -> remitenteMensaje, MTR_DIRECTORIO_NO_BORRO, datosT -> directorioElim,
                                                                                                (int) (datosT -> errorDevuelto));
      estado1 = 0;
      estado2 = 0x08;
      break;
    case 4:
      free(datosT -> directorioElim);
      fat32_destruir_ruta(datosT -> rutaElim);
      free(datosT -> lbpe1);
      fat32_liberar_descriptor(datosT -> descriptor);
      free(datosT);
      estado1 = 0;
      estado2 = 0;
    }
  }
  return (estado2 << 8) | estado1;
}

#endif